/*
 * Copyright 2011-2012 Rivoli team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.rivoli.builder

import com.googlecode.rivoli.RivoliException
import com.googlecode.rivoli.configuration.Configuration
import com.googlecode.rivoli.model.Element
import com.googlecode.rivoli.model.Model
import com.googlecode.rivoli.model.support.ElementDescriptorSupport
import com.googlecode.rivoli.reader.DefinitionReader
import com.googlecode.rivoli.writer.Writer

import org.testng.annotations.BeforeMethod
import org.testng.annotations.Test

class GeneratorTest {
	private Configuration configuration

	private ByteArrayOutputStream out

	@BeforeMethod
	void createConfiguration() {
		configuration = new Configuration()
		configuration.addConfigurable('model', [:] as Model)
		configuration.addConfigurable('reader', [read: {String name, Model model, Map<String, ?> data ->
			new Element(new ElementDescriptorSupport(data['name'] ?: name))
		}] as DefinitionReader)
		configuration.addConfigurable('writer', [write: {Element element, OutputStream out ->
			out.write(element.descriptor.name.bytes)
		}] as Writer)

		out = new ByteArrayOutputStream()
	}

	@Test(expectedExceptions = RivoliException)
	void 'definition name should be required'() {
		Generator.generate(configuration) {
			out = this.out
		}
	}

	@Test(expectedExceptions = RivoliException)
	void 'output stream should be required'() {
		Generator.generate(configuration) {
			name = 'test'
		}
	}

	@Test(expectedExceptions = RivoliException)
	void 'using unknown configurable name should not be allowed'() {
		Generator.generate(configuration) {
			writer = 'upper case'

			name = 'test'
			out = this.out
		}
	}

	@Test
	void 'names of configurables should not be required when there is no ambiguity'() {
		Generator.generate(configuration) {
			name = 'test'
			out = this.out
		}

		assert out.toString() == 'test'
	}

	@Test(expectedExceptions = RivoliException)
	void 'not resolving configurable ambiguity should not be allowed'() {
		configuration.addConfigurable('test writer', [:] as Writer)

		Generator.generate(configuration) {
			name = 'test'
			out = this.out
		}
	}

	@Test
	void 'specifying name of configurable should resolve ambiguity'() {
		configuration.addConfigurable('upper case', [write: {Element element, OutputStream out ->
			out.write(element.descriptor.name.toUpperCase().bytes)
		}] as Writer)

		Generator.generate(configuration) {
			writer = 'upper case'

			name = 'test'
			out = this.out
		}

		assert out.toString() == 'TEST'
	}

	@Test
	void 'data should be mutable'() {
		Generator.generate(configuration) {
			data['name'] = 'data'

			name = 'test'
			out = this.out
		}

		assert out.toString() == 'data'
	}
}